using System;
using Server.Network;
using Server.Gumps;

namespace Server.Items
{
    public class SOS : Item
    {
        public override int LabelNumber
        {
            get
            {
                if (IsAncient)
                    return 1063450; // an ancient SOS

                return 1041081; // a waterstained SOS
            }
        }

        private int m_Level;
        private Map m_TargetMap;
        private Point3D m_TargetLocation;

        [CommandProperty(AccessLevel.GameMaster)]
        public bool IsAncient
        {
            get { return (m_Level >= 4); }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int Level
        {
            get { return m_Level; }
            set
            {
                m_Level = Math.Max(1, Math.Min(value, 4));
                UpdateHue();
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Map TargetMap
        {
            get { return m_TargetMap; }
            set { m_TargetMap = value; }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Point3D TargetLocation
        {
            get { return m_TargetLocation; }
            set { m_TargetLocation = value; }
        }

        public void UpdateHue()
        {
            if (IsAncient)
                Hue = 0x481;
            else
                Hue = 0;
        }

        [Constructable]
        public SOS()
            : this(Map.Trammel)
        {
        }

        [Constructable]
        public SOS(Map map)
            : this(map, MessageInABottle.GetRandomLevel())
        {
        }

        [Constructable]
        public SOS(Map map, int level)
            : base(0x14ED)
        {
            Weight = 1.0;

            m_Level = level;
            m_TargetMap = map;
            m_TargetLocation = FindLocation(m_TargetMap);

            UpdateHue();
        }

        public SOS(Serial serial)
            : base(serial)
        {
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write((int)4); // version

            writer.Write(m_Level);

            writer.Write(m_TargetMap);
            writer.Write(m_TargetLocation);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();

            switch (version)
            {
                case 4:
                case 3:
                case 2:
                    {
                        m_Level = reader.ReadInt();
                        goto case 1;
                    }
                case 1:
                    {
                        m_TargetMap = reader.ReadMap();
                        m_TargetLocation = reader.ReadPoint3D();

                        break;
                    }
                case 0:
                    {
                        m_TargetMap = this.Map;

                        if (m_TargetMap == null || m_TargetMap == Map.Internal)
                            m_TargetMap = Map.Trammel;

                        m_TargetLocation = FindLocation(m_TargetMap);

                        break;
                    }
            }

            if (version < 2)
                m_Level = MessageInABottle.GetRandomLevel();

            if (version < 3)
                UpdateHue();

            if (version < 4 && m_TargetMap == Map.Tokuno)
                m_TargetMap = Map.Trammel;
        }

        public override void OnDoubleClick(Mobile from)
        {
            if (IsChildOf(from.Backpack))
            {
                from.CloseGump(typeof(MessageGump));
                from.SendGump(new MessageGump(m_TargetMap, m_TargetLocation));
            }
            else
            {
                from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
            }
        }

        private static int[] m_WaterTiles = new int[]
			{
				0x00A8, 0x00AB,
				0x0136, 0x0137
			};

        private static Rectangle2D[] m_BritRegions = new Rectangle2D[] { new Rectangle2D(0, 0, 5120, 4096) };
        private static Rectangle2D[] m_IlshRegions = new Rectangle2D[] { new Rectangle2D(1472, 272, 304, 240), new Rectangle2D(1240, 1000, 312, 160) };
        private static Rectangle2D[] m_MalasRegions = new Rectangle2D[] { new Rectangle2D(1376, 1520, 464, 280) };

        public static Point3D FindLocation(Map map)
        {
            if (map == null || map == Map.Internal)
                return Point3D.Zero;

            Rectangle2D[] regions;

            if (map == Map.Felucca || map == Map.Trammel)
                regions = m_BritRegions;
            else if (map == Map.Ilshenar)
                regions = m_IlshRegions;
            else if (map == Map.Malas)
                regions = m_MalasRegions;
            else
                regions = new Rectangle2D[] { new Rectangle2D(0, 0, map.Width, map.Height) };

            if (regions.Length == 0)
                return Point3D.Zero;

            for (int i = 0; i < 50; ++i)
            {
                Rectangle2D reg = regions[Utility.Random(regions.Length)];
                int x = Utility.Random(reg.X, reg.Width);
                int y = Utility.Random(reg.Y, reg.Height);

                if (!ValidateDeepWater(map, x, y))
                    continue;

                bool valid = true;

                for (int j = 1, offset = 5; valid && j <= 5; ++j, offset += 5)
                {
                    if (!ValidateDeepWater(map, x + offset, y + offset))
                        valid = false;
                    else if (!ValidateDeepWater(map, x + offset, y - offset))
                        valid = false;
                    else if (!ValidateDeepWater(map, x - offset, y + offset))
                        valid = false;
                    else if (!ValidateDeepWater(map, x - offset, y - offset))
                        valid = false;
                }

                if (valid)
                    return new Point3D(x, y, 0);
            }

            return Point3D.Zero;
        }

        private static bool ValidateDeepWater(Map map, int x, int y)
        {
            int tileID = map.Tiles.GetLandTile(x, y).ID;
            bool water = false;

            for (int i = 0; !water && i < m_WaterTiles.Length; i += 2)
                water = (tileID >= m_WaterTiles[i] && tileID <= m_WaterTiles[i + 1]);

            return water;
        }

        private class MessageGump : Gump
        {
            public MessageGump(Map map, Point3D loc)
                : base(150, 50)
            {
                int xLong = 0, yLat = 0;
                int xMins = 0, yMins = 0;
                bool xEast = false, ySouth = false;
                string fmt;

                if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth))
                    fmt = String.Format("{0}°{1}'{2},{3}°{4}'{5}", yLat, yMins, ySouth ? "S" : "N", xLong, xMins, xEast ? "E" : "W");
                else
                    fmt = "?????";

                AddPage(0);

                AddBackground(0, 40, 350, 300, 2520);

                AddHtmlLocalized(30, 80, 285, 160, 1018326, true, true); /* This is a message hastily scribbled by a passenger aboard a sinking ship.
																			* While it is probably too late to save the passengers and crew,
																			* perhaps some treasure went down with the ship!
																			* The message gives the ship's last known sextant co-ordinates.
																			*/

                AddHtml(35, 240, 230, 20, fmt, false, false);

                AddButton(35, 265, 4005, 4007, 0, GumpButtonType.Reply, 0);
                AddHtmlLocalized(70, 265, 100, 20, 1011036, false, false); // OKAY
            }
        }
    }
}